﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace Gmantis.Controls.DataGrid
{
    internal class VirtualList
    {
        // Fields
        private int _count;
        public Dictionary<int, DataGridRow> _items;

        // Events
        public event Action CountChanged;

        public event Action<DataGridRow> ItemLoaded;

        public event Func<int, DataGridRow> ItemRequested;

        // Methods
        public VirtualList(int count)
        {
            this._count = count;
            this._items = new Dictionary<int, DataGridRow>();
        }

        public void Clear()
        {
            this._count = 0;
            this._items.Clear();
        }

        public IEnumerable<DataGridRow> GetLoadedItems()
        {
            return (from pair in this._items
                    orderby pair.Key
                    select pair.Value);
        }

        public void Insert(int newIndex, DataGridRow newItem)
        {
            if (newIndex != this.Count)
            {
                foreach (KeyValuePair<int, DataGridRow> pair in from pair in this._items
                                                                orderby pair.Key descending
                                                                select pair)
                {
                    if (pair.Key >= newIndex)
                    {
                        this._items.Remove(pair.Key);
                        this._items.Add(pair.Key + 1, pair.Value);
                        pair.Value.LocalIndex = pair.Key + 1;
                    }
                }
            }
            this._items[newIndex] = newItem;
            newItem.LocalIndex = newIndex;
            this.Count++;
        }

        public void Remove(DataGridRow item)
        {
            int localIndex = item.LocalIndex;
            this._items.Remove(localIndex);
            item.LocalIndex = -1;
            foreach (KeyValuePair<int, DataGridRow> pair in from pair in this._items
                                                            orderby pair.Key
                                                            select pair)
            {
                if (pair.Key > localIndex)
                {
                    this._items.Remove(pair.Key);
                    this._items.Add(pair.Key - 1, pair.Value);
                    pair.Value.LocalIndex = pair.Key - 1;
                }
            }
            this.Count--;
        }

        // Properties
        public int Count
        {
            get
            {
                return this._count;
            }
            set
            {
                int num = this._count;
                this._count = value;
                if ((this._count != num) && (this.CountChanged != null))
                {
                    this.CountChanged();
                }
            }
        }

        public DataGridRow this[int index]
        {
            get
            {
                DataGridRow row;
                if ((index < 0) || (index >= this.Count))
                {
                    throw new IndexOutOfRangeException();
                }
                if (!this._items.TryGetValue(index, out row))
                {
                    row = this.ItemRequested(index);
                    row.LocalIndex = index;
                    this._items[index] = row;
                    this.ItemLoaded(row);
                }
                return row;
            }
            set
            {
                if ((index < 0) || (index >= this.Count))
                {
                    throw new IndexOutOfRangeException();
                }
                this._items[index] = value;
            }
        }
    }
}
